home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
tools
/
czesc_3
/
multiuser
/
src
/
library
/
config.c
next >
Wrap
C/C++ Source or Header
|
1994-06-29
|
20KB
|
838 lines
/************************************************************
* MultiUser - MultiUser Task/File Support System *
* --------------------------------------------------------- *
* Configuration *
* --------------------------------------------------------- *
* © Copyright 1993-1994 by Geert Uytterhoeven *
* All Rights Reserved. *
************************************************************/
#include <exec/alerts.h>
#include <exec/execbase.h>
#include <dos/dos.h>
#include <dos/filehandler.h>
#include <libraries/reqtools.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/reqtools.h>
#include <string.h>
#include "Memory.h"
#include "Misc.h"
#include "Config.h"
#include "Locale.h"
#include "LibHeader.h"
/*
* Static Routines
*/
static void ClearBuffer(void);
static void InitDefs(void);
static struct muUserDef *ParseUserLine(STRPTR line, ULONG linenum);
static struct muGroupDef *ParseGroupLine(STRPTR line, ULONG linenum);
static void ParseRelationLine(STRPTR line, ULONG linenum);
static BOOL ReadKeyFiles(void);
static BOOL ReadKeyFile(struct MsgPort *fs);
static BOOL ParseDirLockLine(struct MsgPort *fs, BPTR file, BPTR *dir);
static void RemTerminatingLF(char *buffer);
static void LoadConfig(void);
static STRPTR SafeFGets(BPTR fh, STRPTR buf, ULONG len);
/*
* Configuration Stuff
*/
char KeyFileName[] = muKey_FileName;
char PasswdFileName[] = muPasswd_FileName;
char ConfigFileName[] = muConfig_FileName;
char GroupFileName[] = muGroup_FileName;
char LogFileName[] = muLog_FileName;
BPTR PasswdDirLock = NULL;
BPTR ConfigDirLock = NULL;
struct muUserDef *UserDef = NULL;
struct muGroupDef *GroupDef = NULL;
char Key[12];
BOOL FirstStartup = TRUE;
/*
* General Purpose Buffer
*/
#define GENBUFSIZE 1024
char *Buffer = NULL;
/*
* Passwd and Group File Notification
*/
struct NotifyRequest __aligned PasswdNotifyReq;
struct NotifyRequest __aligned GroupNotifyReq;
/*
* Clear the General Purpose Buffer
*/
static void __inline ClearBuffer(void)
{
memset(Buffer, NULL, GENBUFSIZE);
}
/*
* Get a pointer to the User Definitions
*/
struct muUserDef *GetUserDefs(void)
{
if (!UserDef)
InitDefs();
return(UserDef);
}
/*
* Get a pointer to the Group Definitions
*/
struct muGroupDef *GetGroupDefs(void)
{
if (!GroupDef)
InitDefs();
return(GroupDef);
}
/*
* Initialise the User and Group Definitions
*/
static void InitDefs(void)
{
BPTR file;
ULONG linenum;
CurrentDir(PasswdDirLock);
if (file = Open(PasswdFileName, MODE_OLDFILE)) {
struct muUserDef *def1, *def2 = NULL;
for (linenum = 1; FGets(file, Buffer, GENBUFSIZE-1); linenum++)
/* V36/37: use GENBUFSIZE-1 */
/* V39: use GENBUFSIZE */
if (Buffer[0] && (Buffer[0] != '\n'))
if (def1 = ParseUserLine(Buffer, linenum)) {
if (def2)
def2->Next = def1;
else
UserDef = def1;
def2 = def1;
}
Close(file);
}
CurrentDir(ConfigDirLock);
if (UserDef && (file = Open(GroupFileName, MODE_OLDFILE))) {
struct muGroupDef *def1, *def2 = NULL;
for (linenum = 1; FGets(file, Buffer, GENBUFSIZE-1) && (Buffer[0] != '\n'); linenum++)
/* V36/37: use GENBUFSIZE-1 */
/* V39: use GENBUFSIZE */
if (Buffer[0])
if (def1 = ParseGroupLine(Buffer, linenum)) {
if (def2)
def2->Next = def1;
else
GroupDef = def1;
def2 = def1;
}
if (Buffer[0] == '\n')
for (linenum++; FGets(file, Buffer, GENBUFSIZE-1); linenum++)
/* V36/37: use GENBUFSIZE-1 */
/* V39: use GENBUFSIZE */
if (Buffer[0] && (Buffer[0] != '\n'))
ParseRelationLine(Buffer, linenum);
Close(file);
}
ClearBuffer();
if (!UserDef || !GroupDef)
FreeDefs();
}
/*
* Parse a User Entry
*/
static struct muUserDef *ParseUserLine(STRPTR line, ULONG linenum)
{
int i, j, len;
LONG uid, gid;
struct muUserDef *def;
STRPTR part[7];
STRPTR ptr;
#define UPART_USERID 0
#define UPART_PASSWORD 1
#define UPART_UID 2
#define UPART_GID 3
#define UPART_USERNAME 4
#define UPART_HOMEDIR 5
#define UPART_SHELL 6
i = 0;
for (j = 0; j < 7; j++) {
part[j] = &line[i];
while ((line[i]) && (line[i] != '\n') && (line[i] != '|'))
i++;
if (j == 6)
if (line[i] && (line[i] != '\n'))
goto Fail;
else {}
else if (line[i] != '|')
goto Fail;
line[i++] = '\0';
len = strlen(part[j]);
switch(j) {
case UPART_USERID:
if (!len)
goto Fail;
break;
case UPART_PASSWORD:
if (len && (len != 11))
goto Fail;
break;
case UPART_UID:
if (!len || (StrToLong(part[j], &uid) == -1) || (uid < 1) || (uid > 65535))
goto Fail;
break;
case UPART_GID:
if (!len || (StrToLong(part[j], &gid) == -1) || (gid < 0) || (gid > 65535))
goto Fail;
break;
case UPART_USERNAME:
case UPART_HOMEDIR:
case UPART_SHELL:
break;
}
}
if (def = (struct muUserDef *)MAllocV(sizeof(struct muUserDef)+strlen(part[UPART_USERID])+
strlen(part[UPART_USERNAME])+strlen(part[UPART_HOMEDIR])+
strlen(part[UPART_SHELL])+16)) {
ptr = &((STRPTR)def)[sizeof(struct muUserDef)];
def->UserID = ptr;
strcpy(ptr, part[UPART_USERID]);
ptr = &ptr[strlen(part[UPART_USERID])+1];
def->Password = ptr;
strcpy(ptr, part[UPART_PASSWORD]);
ptr = &ptr[12];
def->uid = (UWORD)uid;
def->gid = (UWORD)gid;
def->UserName = ptr;
strcpy(ptr, part[UPART_USERNAME]);
ptr = &ptr[strlen(part[UPART_USERNAME])+1];
def->HomeDir = ptr;
strcpy(ptr, part[UPART_HOMEDIR]);
ptr = &ptr[strlen(part[UPART_HOMEDIR])+1];
def->Shell = ptr;
strcpy(ptr, part[UPART_SHELL]);
} else
Die(NULL, AN_Unknown | AG_NoMemory);
return(def);
Fail:
Warn(GetLocStr(MSG_BADENTRY_PASSWD), &linenum);
return(NULL);
}
/*
* Parse a Group Entry
*/
static struct muGroupDef *ParseGroupLine(STRPTR line, ULONG linenum)
{
int i, j, len;
LONG gid, mgruid;
struct muGroupDef *def;
STRPTR part[4];
STRPTR ptr;
#define GPART_GROUPID 0
#define GPART_GID 1
#define GPART_MGRUID 2
#define GPART_GROUPNAME 3
i = 0;
for (j = 0; j < 4; j++) {
part[j] = &line[i];
while ((line[i]) && (line[i] != '\n') && (line[i] != '|'))
i++;
if (j == 3)
if (line[i] && (line[i] != '\n'))
goto Fail;
else {}
else if (line[i] != '|')
goto Fail;
line[i++] = '\0';
len = strlen(part[j]);
switch(j) {
case GPART_GROUPID:
if (!len)
goto Fail;
break;
case GPART_GID:
if (!len || (StrToLong(part[j], &gid) == -1) || (gid < 0) || (gid > 65535))
goto Fail;
break;
case GPART_MGRUID:
if (!len || (StrToLong(part[j], &mgruid) == -1) || (mgruid < 0) || (mgruid > 65535))
goto Fail;
break;
case GPART_GROUPNAME:
break;
}
}
if (def = (struct muGroupDef *)MAllocV(sizeof(struct muGroupDef)+strlen(part[GPART_GROUPID])+
strlen(part[GPART_GROUPNAME])+2)) {
ptr = &((STRPTR)def)[sizeof(struct muGroupDef)];
def->GroupID = ptr;
strcpy(ptr, part[GPART_GROUPID]);
ptr = &ptr[strlen(part[GPART_GROUPID])+1];
def->gid = (UWORD)gid;
def->MgrUid = (UWORD)mgruid;
def->GroupName = ptr;
strcpy(ptr, part[GPART_GROUPNAME]);
} else
Die(NULL, AN_Unknown | AG_NoMemory);
return(def);
Fail:
Warn(GetLocStr(MSG_BADENTRY_GROUP), &linenum);
return(NULL);
}
/*
* Parse a Relation Entry
*/
static void ParseRelationLine(STRPTR line, ULONG linenum)
{
struct muUserDef *def;
UWORD *groups;
ULONG numgroups = 0;
LONG uid, gid, len;
ULONG i, j;
if (((len = StrToLong(line, &uid)) == -1) || (uid < 1) || (uid > 65535))
goto Fail;
i = len;
j = i+1;
if (line[i] != ':')
goto Fail;
for (def = UserDef; def && (def->uid != uid); def = def->Next);
if (def) {
do {
if (((len = StrToLong(&line[++i], &gid)) == -1) || (gid < 0) || (gid > 65535))
goto Fail;
i += len;
numgroups++;
if (line[i] && (line[i] != ',') && (line[i] != '\n'))
goto Fail;
} while (line[i] && (line[i] != '\n'));
if (def->NumSecGroups+numgroups <= 65535) {
if (def->NumSecGroups)
if (groups = MAlloc((numgroups+def->NumSecGroups)*sizeof(UWORD))) {
CopyMem(def->SecGroups, groups, def->NumSecGroups*sizeof(UWORD));
Free(def->SecGroups, def->NumSecGroups*sizeof(UWORD));
def->SecGroups = groups;
groups += def->NumSecGroups;
def->NumSecGroups += numgroups;
} else
Die(NULL, AN_Unknown | AG_NoMemory);
else if (groups = MAlloc(numgroups*sizeof(UWORD))) {
def->SecGroups = groups;
def->NumSecGroups = numgroups;
} else
Die(NULL, AN_Unknown | AG_NoMemory);
if (groups)
for (i = 0; i < numgroups; i++) {
j += StrToLong(&line[j++], &gid);
groups[i] = gid;
}
} else {
LONG args[2];
args[0] = uid;
args[1] = linenum;
Warn(GetLocStr(MSG_TOOMANYSECGROUPS), args);
}
} else
Fail:
Warn(GetLocStr(MSG_BADENTRY_GROUP), &linenum);
}
/*
* Free the User and Group Definitions
*/
void FreeDefs(void)
{
struct muUserDef *udef = UserDef;
struct muGroupDef *gdef = GroupDef;
APTR p;
while(udef) {
p = udef->Next;
if (udef->NumSecGroups)
Free(udef->SecGroups, udef->NumSecGroups*sizeof(UWORD));
FreeV(udef);
udef = p;
}
UserDef = NULL;
while(gdef) {
p = gdef->Next;
FreeV(gdef);
gdef = p;
}
GroupDef = NULL;
}
/*
* Update the User Definitions
*
*
* OUT: BOOL Success
*/
BOOL UpdateUserDefs(void)
{
BPTR file;
BOOL res;
struct muUserDef *def = UserDef;
LONG args[7];
CurrentDir(PasswdDirLock);
if (res = (file = Open(PasswdFileName, MODE_NEWFILE))) {
while(def && res) {
args[0] = (LONG)def->UserID;
args[1] = (LONG)def->Password;
args[2] = (LONG)def->uid;
args[3] = (LONG)def->gid;
args[4] = (LONG)def->UserName;
args[5] = (LONG)def->HomeDir;
args[6] = (LONG)def->Shell;
res = (VFPrintf(file, "%s|%s|%ld|%ld|%s|%s|%s\n", args) != -1);
def = def->Next;
}
res = Close(file) && res;
}
return(res);
}
/*
* Find all MultiUserFileSystem volumes
*/
static BOOL FindVolumes(void)
{
struct DosList *dl;
struct FileSysStartupMsg *sm;
struct DosEnvec *de;
BOOL res = FALSE;
struct muVolume **vollist = &muBase->Volumes;
dl = LockDosList(LDF_DEVICES|LDF_READ);
while (dl = NextDosEntry(dl,LDF_DEVICES))
if ((dl->dol_Task) && ((LONG)(sm = BADDR(dl->dol_misc.dol_handler.dol_Startup)) > 1024) &&
(de = BADDR(sm->fssm_Environ)) && (de->de_TableSize >= DE_DOSTYPE) &&
(de->de_DosType == ID_MUFS_DISK))
if (*vollist = (struct muVolume *)MAlloc(sizeof(struct muVolume))) {
(*vollist)->DosList = dl;
(*vollist)->Process = dl->dol_Task;
vollist = &(*vollist)->Next;
res = TRUE;
} else
Die(NULL, AN_Unknown | AG_NoMemory);
UnLockDosList(LDF_DEVICES|LDF_READ);
return(res);
}
/*
* Read and parse the Key Files
*/
static BOOL ReadKeyFiles(void)
{
struct muVolume *vol;
BOOL res = FALSE;
for (vol = muBase->Volumes; vol && (res = ReadKeyFile(vol->Process)); vol = vol->Next);
return((BOOL)(res && PasswdDirLock && ConfigDirLock));
}
static BOOL ReadKeyFile(struct MsgPort *fs)
{
BPTR dir, file;
char buffer[12];
BOOL res;
static char __aligned name[] = "\1:";
if (res = (dir = DoPkt(fs, ACTION_LOCATE_OBJECT, NULL, MKBADDR(name), ACCESS_READ, NULL, NULL))) {
CurrentDir(dir);
if (res = (file = Open(KeyFileName, MODE_OLDFILE))) {
if (res = (BOOL)SafeFGets(file, Buffer, GENBUFSIZE-1)) {
/* V36/37: use GENBUFSIZE-1 */
/* V39: use GENBUFSIZE */
RemTerminatingLF(Buffer);
if (Encrypt(buffer, Buffer, "Alpha, PowerPC or R4400?")) {
if (Key[0])
res = !strcmp(Key, buffer);
else
strcpy(Key, buffer);
if (res)
res = ParseDirLockLine(fs, file, &PasswdDirLock) &&
ParseDirLockLine(fs, file, &ConfigDirLock);
}
}
Close(file);
ClearBuffer();
}
UnLock(dir);
}
return(res);
}
/*
* Parse a Key File Line and Lock the appropriate Directory
*/
static BOOL ParseDirLockLine(struct MsgPort *fs, BPTR file, BPTR *dir)
{
BOOL res;
if (res = (BOOL)FGets(file, Buffer+1, GENBUFSIZE-2)) {
/* V36/37: use GENBUFSIZE-2 */
/* V39: use GENBUFSIZE-1 */
RemTerminatingLF(Buffer);
if (Buffer[1])
if (*dir)
res = FALSE;
else {
Buffer[0] = strlen(Buffer+1);
res = *dir = DoPkt(fs, ACTION_LOCATE_OBJECT, NULL, MKBADDR(Buffer), ACCESS_READ, NULL, NULL);
}
}
return(res);
}
static void RemTerminatingLF(char *buffer)
{
int i;
for (i = 0; buffer[i]; i++);
if (i && (buffer[i-1] == '\n'))
buffer[i-1] = '\0';
}
/*
* Load the Configuration file
*/
static void LoadConfig(void)
{
BPTR file;
LONG *argarray[12];
#define argLIMITDOSSETPROTECTION 0
#define argPROFILE 1
#define argLASTLOGINREQ 2
#define argLOGSTARTUP 3
#define argLOGLOGIN 4
#define argLOGLOGINFAIL 5
#define argLOGPASSWD 6
#define argLOGPASSWDFAIL 7
#define argLOGCHECKPASSWD 8
#define argLOGCHECKPASSWDFAIL 9
#define argPASSWDUIDLEVEL 10
#define argPASSWDGIDLEVEL 11
struct RDArgs *rdargs;
ULONG line;
struct muConfig config;
config.Flags = muCFGF_LimitDOSSetProtection | muCFGF_Profile | muCFGF_LastLoginReq;
config.LogFlags = NULL;
config.PasswduidLevel = 0;
config.PasswdgidLevel = 0;
if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
CurrentDir(ConfigDirLock);
if (file = Open(ConfigFileName, MODE_OLDFILE)) {
for (line = 1; FGets(file, Buffer, GENBUFSIZE-1); line++) {
/* V36/37: use GENBUFSIZE-1 */
/* V39: use GENBUFSIZE */
rdargs->RDA_Source.CS_Buffer = Buffer;
rdargs->RDA_Source.CS_Length = strlen(Buffer);
rdargs->RDA_Source.CS_CurChr = 0;
rdargs->RDA_DAList = NULL;
rdargs->RDA_Buffer = NULL;
rdargs->RDA_BufSiz = NULL;
rdargs->RDA_ExtHelp = NULL;
rdargs->RDA_Flags = RDAF_NOPROMPT;
memset(argarray, NULL, sizeof(argarray));
if (ReadArgs("LIMITDOSSETPROTECTION/K/N,PROFILE/K/N,LASTLOGINREQ/K/N,LOGSTARTUP/K/N,"
"LOGLOGIN/K/N,LOGLOGINFAIL/K/N,LOGPASSWD/K/N,LOGPASSWDFAIL/K/N,"
"LOGCHECKPASSWD/K/N,LOGCHECKPASSWDFAIL/K/N,PASSWDUIDLEVEL/K/N,"
"PASSWDGIDLEVEL/K/N", (LONG *)argarray, rdargs)) {
if (argarray[argLIMITDOSSETPROTECTION])
if (*argarray[argLIMITDOSSETPROTECTION])
config.Flags |= muCFGF_LimitDOSSetProtection;
else
config.Flags &= ~muCFGF_LimitDOSSetProtection;
if (argarray[argPROFILE])
if (*argarray[argPROFILE])
config.Flags |= muCFGF_Profile;
else
config.Flags &= ~muCFGF_Profile;
if (argarray[argLASTLOGINREQ])
if (*argarray[argLASTLOGINREQ])
config.Flags |= muCFGF_LastLoginReq;
else
config.Flags &= ~muCFGF_LastLoginReq;
if (argarray[argLOGSTARTUP])
if (*argarray[argLOGSTARTUP])
config.LogFlags |= muLogF_Startup;
else
config.LogFlags &= ~muLogF_Startup;
if (argarray[argLOGLOGIN])
if (*argarray[argLOGLOGIN])
config.LogFlags |= muLogF_Login;
else
config.LogFlags &= ~muLogF_Login;
if (argarray[argLOGLOGINFAIL])
if (*argarray[argLOGLOGINFAIL])
config.LogFlags |= muLogF_LoginFail;
else
config.LogFlags &= ~muLogF_LoginFail;
if (argarray[argLOGPASSWD])
if (*argarray[argLOGPASSWD])
config.LogFlags |= muLogF_Passwd;
else
config.LogFlags &= ~muLogF_Passwd;
if (argarray[argLOGPASSWDFAIL])
if (*argarray[argLOGPASSWDFAIL])
config.LogFlags |= muLogF_PasswdFail;
else
config.LogFlags &= ~muLogF_PasswdFail;
if (argarray[argLOGCHECKPASSWD])
if (*argarray[argLOGCHECKPASSWD])
config.LogFlags |= muLogF_CheckPasswd;
else
config.LogFlags &= ~muLogF_CheckPasswd;
if (argarray[argLOGCHECKPASSWDFAIL])
if (*argarray[argLOGCHECKPASSWDFAIL])
config.LogFlags |= muLogF_CheckPasswdFail;
else
config.LogFlags &= ~muLogF_CheckPasswdFail;
if (argarray[argPASSWDUIDLEVEL])
if (*argarray[argPASSWDUIDLEVEL] > 65535)
Warn(GetLocStr(MSG_BADVALUE_CONFIG), &line);
else
config.PasswduidLevel = *argarray[argPASSWDUIDLEVEL];
if (argarray[argPASSWDGIDLEVEL])
if (*argarray[argPASSWDGIDLEVEL] > 65535)
Warn(GetLocStr(MSG_BADVALUE_CONFIG), &line);
else
config.PasswdgidLevel = *argarray[argPASSWDGIDLEVEL];
} else
Warn(GetLocStr(MSG_BADOPTION_CONFIG), &line);
FreeArgs(rdargs);
}
Close(file);
ClearBuffer();
} else
Warn(GetLocStr(MSG_NOCONFIGFILE), NULL);
FreeDosObject(DOS_RDARGS, rdargs);
} else
Die(NULL, AN_Unknown | AG_NoMemory);
muBase->Config.Flags = config.Flags;
muBase->Config.LogFlags = config.LogFlags;
muBase->Config.PasswduidLevel = config.PasswduidLevel;
muBase->Config.PasswdgidLevel = config.PasswdgidLevel;
if (FirstStartup) {
FirstStartup = FALSE;
if (muBase->Config.LogFlags & muLogF_Startup)
VLogF("Startup", NULL);
}
}
/*
* Initialise the Volume Information
*/
BOOL InitVolumes(void)
{
if (!(Buffer = MAlloc(GENBUFSIZE)))
Die(NULL, AN_Unknown | AG_NoMemory);
ObtainSemaphore(&muBase->VolumesSem);
if (!FindVolumes())
Die(GetLocStr(MSG_NOMUFS), NULL);
if (!ReadKeyFiles()) {
muBase->SecurityViolation = TRUE;
Die(GetLocStr(MSG_BADKEYFILE), NULL);
}
ReleaseSemaphore(&muBase->VolumesSem);
LoadConfig();
CurrentDir(PasswdDirLock);
memset(&PasswdNotifyReq, NULL, sizeof(PasswdNotifyReq));
PasswdNotifyReq.nr_Name = PasswdFileName;
PasswdNotifyReq.nr_Flags = NRF_SEND_SIGNAL;
PasswdNotifyReq.nr_stuff.nr_Signal.nr_Task = (struct Task *)SysBase->ThisTask;
PasswdNotifyReq.nr_stuff.nr_Signal.nr_SignalNum = muBase->NotifySig;
StartNotify(&PasswdNotifyReq);
CurrentDir(ConfigDirLock);
memset(&GroupNotifyReq, NULL, sizeof(GroupNotifyReq));
GroupNotifyReq.nr_Name = GroupFileName;
GroupNotifyReq.nr_Flags = NRF_SEND_SIGNAL;
GroupNotifyReq.nr_stuff.nr_Signal.nr_Task = (struct Task *)SysBase->ThisTask;
GroupNotifyReq.nr_stuff.nr_Signal.nr_SignalNum = muBase->NotifySig;
StartNotify(&GroupNotifyReq);
return(TRUE);
}
/*
* Free all Volume Information
*/
void FreeVolumes(void)
{
struct muVolume *vollist, *vl2;
FreeDefs();
EndNotify(&GroupNotifyReq);
EndNotify(&PasswdNotifyReq);
if (PasswdDirLock) {
UnLock(PasswdDirLock);
PasswdDirLock = NULL;
}
if (ConfigDirLock) {
UnLock(ConfigDirLock);
ConfigDirLock = NULL;
}
ObtainSemaphore(&muBase->VolumesSem);
vollist = muBase->Volumes;
while (vollist) {
vl2 = vollist->Next;
Free(vollist, sizeof(struct muVolume));
vollist = vl2;
}
muBase->Volumes = NULL;
ReleaseSemaphore(&muBase->VolumesSem);
memset(Key, NULL, sizeof(Key));
if (Buffer) {
Free(Buffer, GENBUFSIZE);
Buffer = NULL;
}
}
/*
* Check whether a Process belongs to a muFS Volume
*/
BOOL CheckmuFSVolume(struct MsgPort *port)
{
struct muVolume *vollist;
BOOL res = FALSE;
ObtainSemaphoreShared(&muBase->VolumesSem);
for (vollist = muBase->Volumes; vollist && !(res = (vollist->Process == port));
vollist = vollist->Next);
ReleaseSemaphore(&muBase->VolumesSem);
return(res);
}
/*
* Format and dump a string to the Log File
*/
void VLogF(STRPTR fmt, LONG *argv)
{
BPTR file;
char date[LEN_DATSTRING];
char time[LEN_DATSTRING];
struct DateTime dt;
LONG args[2];
CurrentDir(ConfigDirLock);
if (file = Open(LogFileName, MODE_READWRITE)) {
if (Seek(file, 0, OFFSET_END) != -1) {
DateStamp(&dt.dat_Stamp);
dt.dat_Format = FORMAT_DOS;
dt.dat_Flags = NULL;
dt.dat_StrDay = NULL;
dt.dat_StrDate = date;
dt.dat_StrTime = time;
DateToStr(&dt);
args[0] = (LONG)date;
args[1] = (LONG)time;
VFPrintf(file, "%s, %s: ", args);
VFPrintf(file, fmt, argv);
FPutC(file, '\n');
}
Close(file);
}
}
/*
* 'Safe' FGets
*
* Prevents synchronization problems on startup
*/
static STRPTR SafeFGets(BPTR fh, STRPTR buf, ULONG len)
{
STRPTR res;
int i;
if (!(res = FGets(fh, buf, len)))
for (i = 1; !res && (i < 10); i++) {
Delay(25);
res = FGets(fh, buf, len);
}
return(res);
}